<?php
/**
 * Model
 *
 * 模型基类
 *
 * @author   songhuan <iphper@yeah.net>
 * @version   $Id: Model.php 1 2010-08-10 14:40:00Z $
 */
abstract class Model extends Table
{
	/**
	 * @var array 所有的错误记录
	 */
    protected $_errors = array();
	
	const INSERT = 0;
	const UPDATE = 1;
	const BOTH = 2;
	
	/**
	 * 初始化父类$_table, $_idField, $_properties值
	 */
	public function __construct()
	{
		if (null === $this->_table)
			$this->_table = strtolower(substr(get_class($this), 0, -strlen(V::$config['model']['modelKey'])));
		
		parent::__construct();
		
		if (method_exists($this, 'init')) 
			$this->init();
			
		if ($this->properties) 
			$this->_addProperties($this->properties);
	}
	
	/**
	 * 自动验证表单
	 * 
	 * @param int $id 
	 * @param array $params 表单数据，如果为空，默认从$_REQUEST中取值
	 * @return boolean 表单数据是否正确
	 */
	public function autoSave($id = 0, array $params = array())
	{	
		$this->setId($id);
		$do = $this->getId() > 0 ? self::UPDATE : self::INSERT; 

		$this->preAutoSave();
		
		if (empty($params))
			$params = &$_REQUEST;
		else 
			$params = array_merge($_REQUEST, $params);
		
		$validatorsfile = API_DIR . DS . 'validators' . DS;
		
		foreach ($this->rules as $field => $rule) 
		{
			$value = array_key_exists($field, $params) ? $params[$field] : null;
			
			if (array_key_exists('when', $rule) && 
				$rule['when'] !== self::BOTH && 
				$rule['when'] !== $do) continue;
				
			foreach ($rule as $method => $arg)
			{
				if (strcasecmp('when', $method) === 0) 
					continue;
					
				$func = ucfirst($method) . 'Validator';
				require_once $validatorsfile . $func . '.php';
				if (!$func($this, $value, $arg)) 
				{
					$this->addError($field, $this->messages[$field][$method]);
					break;
				}
			}
		}
		
		if (!$this->hasError()) 
		{
			if (array_key_exists($this->_idField, $params)) 
				unset($params[$this->_idField]);
			
			$this->initProperties($params, true);
			$this->save();
		}
		
		return !$this->hasError();
	}
	
 	/**
     * 添加一条错误记录
     * 
     * @param string $key 字段名
     * @param string $val 字段值
     * @return void
     */
    public function addError($key, $val)
    {
        if (array_key_exists($key, $this->_errors)) 
        {
            if (!is_array($this->_errors[$key]))
                $this->_errors[$key] = array($this->_errors[$key]);

            $this->_errors[$key][] = $val;
        }
        else
            $this->_errors[$key] = $val;
    }
    
	/**
     * 通过键名获取一条错误信息
     * 
     * @param string $key
     * @return string|null 错误记录
     */
    public function getError($key = null)
    {
    	if (empty($this->_errors))
    		return null;
    	
    	if (null === $key)
    		return array_shift(array_slice($this->_errors, 0, 1));
    	
        if ($this->hasError($key))
            return $this->_errors[$key];
		
        return null;
    }
	
    /**
     * @return array 返回所有的错误信息
     */
    public function getErrors()
    {
        return $this->_errors;
    }
    
	/**
     * 判读某个错误记录是否存在
     * 
     * @param string $key
     * @return boolean
     */
    public function hasError($key = null)
    {
        if (null === $key)
            return count($this->_errors) > 0;

        return array_key_exists($key, $this->_errors);
    }
    
	/**
	 * 自动验证表单之前调用
	 * 
	 * @return boolean 
	 */
	protected function preAutoSave()
	{
	}
}
